import * as Cesium from "cesium"
import type { MatrixTransformOption } from "../../src/types/index"
/**
 * @description 获取从某一点到另一点的平移矩阵
 */
export function getTranslationMatrix(
  start: Cesium.Cartesian3,
  end: Cesium.Cartesian3,
) {
  const translation = Cesium.Cartesian3.subtract(
    end,
    start,
    new Cesium.Cartesian3(),
  )
  const translationMatrix = Cesium.Matrix4.fromTranslation(translation)
  return translationMatrix
}

/**
 * @description 模型矩阵变换，实现了三轴平移、旋转、缩放，支持gltf、3dtileset对象
 * @param tileSet
 * @param options
 * @returns
 */
export function modelMatrixTransform(
  model: Cesium.Cesium3DTileset | Cesium.Model,
  option: MatrixTransformOption,
) {
  const { tx = 0, ty = 0, tz = 0, rx = 0, ry = 0, rz = 0, scale = 1 } = option
  let sx,
    sy,
    sz = undefined
  if (typeof scale === "number") {
    sx = sy = sz = scale
  } else {
    sx = scale.sx
    sy = scale.sy
    sz = scale.sz
  }

  //定义以模型中心为原点的局部坐标转换
  const center = model.boundingSphere.center
  const m = Cesium.Transforms.eastNorthUpToFixedFrame(center)

  //平移参数初始化
  const _tx = tx ? tx : 0
  const _ty = ty ? ty : 0
  const _tz = tz ? tz : 0

  //构建平移向量
  const tempTranslation = new Cesium.Cartesian3(_tx, _ty, _tz)

  //平移向量转换到世界坐标;
  const offset = Cesium.Matrix4.multiplyByPoint(
    m,
    tempTranslation,
    new Cesium.Cartesian3(0, 0, 0),
  )

  //计算世界坐标下的平移向量
  const translation = Cesium.Cartesian3.subtract(
    offset,
    center,
    new Cesium.Cartesian3(),
  )
  //平移向量应用到模型
  model.modelMatrix = Cesium.Matrix4.multiply(
    Cesium.Matrix4.fromTranslation(translation),
    model.modelMatrix,
    new Cesium.Matrix4(),
  )

  //旋转及缩放
  if (rx || ry || rz || sx || sy || sz) {
    //保存原始位置
    const initialCenter = Cesium.Cartesian3.clone(model.boundingSphere.center)
    // 构建模型平移到原点矩阵
    const translationMatrix = Cesium.Matrix4.fromTranslation(
      Cesium.Cartesian3.negate(
        model.boundingSphere.center,
        new Cesium.Cartesian3(),
      ),
    )

    // 定义旋转角度（单位：弧度）
    const radiansX = Cesium.Math.toRadians(rx)
    const radiansY = Cesium.Math.toRadians(ry)
    const radiansZ = Cesium.Math.toRadians(rz)

    // 创建旋转矩阵
    const rotationX = Cesium.Matrix3.fromRotationX(radiansX)
    const rotationY = Cesium.Matrix3.fromRotationY(radiansY)
    const rotationZ = Cesium.Matrix3.fromRotationZ(radiansZ)

    // 组合旋转矩阵
    const combinedRotation = Cesium.Matrix3.multiply(
      rotationX,
      rotationY,
      new Cesium.Matrix3(),
    )
    Cesium.Matrix3.multiply(combinedRotation, rotationZ, combinedRotation)

    // 将 3x3 旋转矩阵转换为 4x4 矩阵
    const rotationMatrix4 = Cesium.Matrix4.fromRotation(combinedRotation)

    //构建缩放矩阵
    const scaleMatrix4 = Cesium.Matrix4.fromScale(
      new Cesium.Cartesian3(sx, sy, sz),
      new Cesium.Matrix4(),
    )

    //构建平移复位矩阵
    const translationBack = Cesium.Matrix4.fromTranslation(initialCenter)

    //组合矩阵
    let tempMatrix = model.modelMatrix
    //应用移到原点
    tempMatrix = Cesium.Matrix4.multiply(
      translationMatrix,
      tempMatrix,
      new Cesium.Matrix4(),
    )
    //应用旋转矩阵
    tempMatrix = Cesium.Matrix4.multiply(
      rotationMatrix4,
      tempMatrix,
      new Cesium.Matrix4(),
    )
    //应用缩放矩阵
    tempMatrix = Cesium.Matrix4.multiply(
      scaleMatrix4,
      tempMatrix,
      new Cesium.Matrix4(),
    )
    //应用复位矩阵
    tempMatrix = Cesium.Matrix4.multiply(
      translationBack,
      tempMatrix,
      new Cesium.Matrix4(),
    )
    model.modelMatrix = tempMatrix
  }

  return model
}

/**
 * @description 调整3dtiles高度
 * @param tileset ——Cesium3DTileset实例
 * @param height ——平移高度，单位：米
 * @returns void
 * @example cesium2s.adjust3DTilesetHeight(tileset,40) //将3dtils模型向上平移40米
 */
export function adjust3DTilesetHeight(
  tileset: Cesium.Cesium3DTileset,
  height: number,
) {
  if (!tileset || typeof height !== "number") {
    console.error("Invalid tileset or height")
    return
  }

  //1.获取原始坐标
  const originalCenter = tileset.boundingSphere.center

  //2.计算高度调整height米后的坐标;
  const originalCarPoint = Cesium.Cartographic.fromCartesian(originalCenter)
  originalCarPoint.height += height
  const { longitude, latitude, height: alt } = originalCarPoint
  const adjustedCenter = Cesium.Cartesian3.fromRadians(longitude, latitude, alt)

  //3. 从起始点和终点计算平移向量
  const translationVector = Cesium.Cartesian3.subtract(
    adjustedCenter,
    originalCenter,
    new Cesium.Cartesian3(),
  )

  //4. 计算平移变换矩阵
  const transform = Cesium.Matrix4.fromTranslation(translationVector)

  //5. 原矩阵乘以变换矩阵并应用到模型的modelMatrix
  const finalMatrix = Cesium.Matrix4.multiply(
    transform,
    tileset.modelMatrix,
    new Cesium.Matrix4(),
  )
  tileset.modelMatrix = finalMatrix
}

/**
 * 为Entity添加坐标轴可视化
 * @param entity 目标Entity
 * @param length 坐标轴长度（米）
 */
export function addAxisToEntity(
  viewer: Cesium.Viewer,
  entity: Cesium.Entity,
  length: number = 10,
) {
  const position = entity.position?.getValue(Cesium.JulianDate.now())
  if (!position) return

  console.log(entity, "orientation")

  const axes = [
    { color: Cesium.Color.RED, direction: Cesium.Cartesian3.UNIT_X }, // X轴（东）
    { color: Cesium.Color.GREEN, direction: Cesium.Cartesian3.UNIT_Y }, // Y轴（北）
    { color: Cesium.Color.BLUE, direction: Cesium.Cartesian3.UNIT_Z }, // Z轴（上）
  ]

  axes.forEach((axis) => {
    const endPoint = Cesium.Cartesian3.add(
      position,
      Cesium.Cartesian3.multiplyByScalar(
        axis.direction,
        length,
        new Cesium.Cartesian3(),
      ),
      new Cesium.Cartesian3(),
    )

    viewer.entities.add({
      polyline: {
        positions: [position, endPoint],
        width: 2,
        material: axis.color,
      },
      parent: entity, // 设置为子实体，随父实体移动
    })
  })
}
